// *************************************************************************************************
//
// MK3D Engine
// --------------------------------------
// Copyright (C) 2007-2011 Zeb (mailto: zebbey@gmail.com)
//
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//
// *************************************************************************************************

#include "mk_header.h"
#include "mk_ui_edit_box.h"
#include "mk_ui_manager.h"
#include "mk_engine.h"

namespace MK3DE
{
    CUIEditBox::CUIEditBox(CUIRenderer* renderer, CUIWindow* parent, D3DXVECTOR2& pos, D3DXVECTOR2& size, const char* name) :
        CUIWindow(renderer, parent, pos, size, name)
    {
        
    }

    CUIEditBox::~CUIEditBox()
    {
        
    }


    BOOL CUIEditBox::Update(DWORD dt)
    {
        _appearence.SetCurrentLook(0);

        if (CUIWindow::GetFocus() == this)
            _appearence.SetCurrentLook(1);

        return TRUE;
    }

    BOOL CUIEditBox::Render()
    {
        SUIQuad* quad = NULL;
        int index = -1;
        while (_appearence.GetNextQuad(quad, index))
        {
            Rect2D src = quad->rcSrc;
            Rect2D dest = quad->rcDest;
            src.SetOffset(_pos.x, _pos.y);
            dest.SetOffset(_pos.x, _pos.y);
            _renderer->RenderQuad(quad->texture, src, dest, quad->color);
        }

        if (CUIWindow::GetFocus() == this)
        {
            float x, y, width, height;
            _fontRender.GetStartPos(x, y);
            _fontRender.GetDimension(width, height);

            static RectColor color;
            static DWORD tick = GetTickCount();
            static DWORD CARET_COLOR1[] = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff };
            static DWORD CARET_COLOR2[] = { 0, 0, 0, 0 };
            if (GetTickCount() - tick > 500)
            {
                tick = GetTickCount();
                if (color.leftBottom == 0xffffffff)
                    color.SetColor(CARET_COLOR2);
                else
                    color.SetColor(CARET_COLOR1);
            }

            Rect2D rcDest(x + width, y, x + width + 1, y + height);
            float right = _pos.x + _size.x - _border;
            if (rcDest.leftTop.x > right)
            {
                rcDest.leftTop.x = right;
                rcDest.rightBottom.x = rcDest.leftTop.x + 1;
            }
            _renderer->RenderQuad(NULL, rcDest, rcDest, color);
        }


        _renderer->FlushRender();

        _fontRender.Render();


        return CUIWindow::Render();
    }

    BOOL CUIEditBox::MouseMsgProc(UIInputEvent& event)
    {
        switch (event.type)
        {
        case UI_IET_LBUTTON_DOWN:
            {
                CUIWindow::SetFocus(this);
                return TRUE;
            }
            break;
        };

        return FALSE;
    }

    BOOL CUIEditBox::KeyboardMsgProc(UIInputEvent& event)
    {
        if (CUIWindow::GetFocus() != this)
            return FALSE;

        if (event.type == UI_IET_CHAR)
        {
            switch (event.key)
            {
            case VK_BACK:
                {
                    std::wstring& text = _fontRender.GetText();
                    if (text.size())
                        text.erase(text.end() - 1);
                    _fontRender.UpdateTextDimension();
                    _fontRender.Recalculate();
                    return TRUE;
                }
                break;

            case 24:        // Ctrl-X Cut
            case VK_CANCEL: // Ctrl-C Copy
            case 22:        // Ctrl-V Paste
            case 1:         // Ctrl-A Select All
            case VK_RETURN:
            // Junk characters we don't want in the string
            case 26:  // Ctrl Z
            case 2:   // Ctrl B
            case 14:  // Ctrl N
            case 19:  // Ctrl S
            case 4:   // Ctrl D
            case 6:   // Ctrl F
            case 7:   // Ctrl G
            case 10:  // Ctrl J
            case 11:  // Ctrl K
            case 12:  // Ctrl L
            case 17:  // Ctrl Q
            case 23:  // Ctrl W
            case 5:   // Ctrl E
            case 18:  // Ctrl R
            case 20:  // Ctrl T
            case 25:  // Ctrl Y
            case 21:  // Ctrl U
            case 9:   // Ctrl I
            case 15:  // Ctrl O
            case 16:  // Ctrl P
            case 27:  // Ctrl [
            case 29:  // Ctrl ]
            case 28:  // Ctrl \ 
                break;
            default:
                {
                    char s[3];
                    if (event.ime)
                    {
                        wchar_t key = (wchar_t)event.key;
                        s[0] = HIBYTE(key);
                        s[1] = LOBYTE(key);
                        s[2] = 0;
                    }
                    else
                    {
                        s[0] = (char)event.key;
                        s[1] = 0;
                    }
                    wchar_t buf[2];
                    MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, s, 2, buf, 1);
                    buf[1] = 0;
                    _fontRender.GetText().append(buf);
                    _fontRender.UpdateTextDimension();
                    _fontRender.Recalculate();
                    return TRUE;
                }
            }

        }

        return FALSE;
    }

    void CUIEditBox::MakeDefaultAppearence()
    {
        // normal
        _appearence.AddLook();
        SUIQuad quad;
        quad.rcDest.SetRect(0, 0, _size.x, _size.y);

        quad.color.SetColor(UIDAC_PANEL_BG_NORMAL);
        _appearence.AddQuad(quad);

        quad.rcDest.SetRect(0, 0, 1, _size.y);
        quad.color.SetColor(UIDAC_BORDER_LIGHT);
        _appearence.AddQuad(quad);

        quad.rcDest.SetRect(0, 0, _size.x, 1);
        quad.color.SetColor(UIDAC_BORDER_LIGHT);
        _appearence.AddQuad(quad);

        quad.rcDest.SetRect(_size.x, 0, _size.x - 1, _size.y);
        quad.color.SetColor(UIDAC_BORDER_DARK);
        _appearence.AddQuad(quad);

        quad.rcDest.SetRect(0, _size.y - 1, _size.x, _size.y);
        quad.color.SetColor(UIDAC_BORDER_DARK);
        _appearence.AddQuad(quad);

        // focus
        _appearence.AddLook();
        quad.rcDest.SetRect(0, 0, _size.x, _size.y);

        quad.color.SetColor(UIDAC_PANEL_BG_FOCUS);
        _appearence.AddQuad(quad);

        quad.rcDest.SetRect(0, 0, 1, _size.y);
        quad.color.SetColor(UIDAC_BORDER_LIGHT);
        _appearence.AddQuad(quad);

        quad.rcDest.SetRect(0, 0, _size.x, 1);
        quad.color.SetColor(UIDAC_BORDER_LIGHT);
        _appearence.AddQuad(quad);

        quad.rcDest.SetRect(_size.x, 0, _size.x - 1, _size.y);
        quad.color.SetColor(UIDAC_BORDER_DARK);
        _appearence.AddQuad(quad);

        quad.rcDest.SetRect(0, _size.y - 1, _size.x, _size.y);
        quad.color.SetColor(UIDAC_BORDER_DARK);
        _appearence.AddQuad(quad);
    }
}